﻿/*
 * datetime.hpp
 *
 *  Created on: 2017年7月6日
 *      Author: work
 */

#ifndef _DM_DATETIME_HPP_
#define _DM_DATETIME_HPP_

#include <dm/export.hpp>

#ifndef DM_API_MISC
#define DM_API_MISC DM_API_IMPORT
#endif

#include <dm/types.hpp>
#include <iostream>
#include <string>

namespace dm{

class CTimeStamp;
class CRunTimeStamp;

class DM_API_MISC CDateTime{
public:
	/**
	 * 星期
	 */
	enum EWeekDay{
		Sunday = 0,//!< Sunday
		Monday,    //!< Monday
		Tuesday,   //!< Tuesday
		Wednesday, //!< Wednesday
		Thursday,  //!< Thursday
		Friday,    //!< Friday
		Saturday   //!< Saturday
	};

	CDateTime();
	CDateTime( const CDateTime& dt );
	CDateTime( const CTimeStamp& ts );
	CDateTime( const CRunTimeStamp& rts );

	CDateTime( const volatile CDateTime& dt );
	CDateTime( const volatile CTimeStamp& ts );
	CDateTime( const volatile CRunTimeStamp& rts );

	CDateTime& operator=( const CDateTime& dt );
	CDateTime& operator=( const CTimeStamp& ts );
	CDateTime& operator=( const CRunTimeStamp& rts );

	CDateTime& operator=( const volatile CDateTime& dt );
	CDateTime& operator=( const volatile CTimeStamp& ts );
	CDateTime& operator=( const volatile CRunTimeStamp& rts );

	bool operator==( const CDateTime& dt )const;

	bool isValid()const;

	inline const dm::uint16& year()const{
		return m_year;
	}

	inline const dm::uint8& month()const{
		return m_month;
	}

	inline const dm::uint8& day()const{
		return m_day;
	}

	inline const dm::uint8& hour()const{
		return m_hour;
	}

	inline const dm::uint8& minute()const{
		return m_minute;
	}

	inline const dm::uint8& sec()const{
		return m_sec;
	}

	inline const dm::uint16& msec()const{
		return m_msec;
	}

	EWeekDay getWeekDay()const;
	inline const char* weekStr()const{
		return weekStr(getWeekDay());
	}

	void setYear( dm::uint16 year );
	void setMonth( dm::uint8 month );
	void setDay( dm::uint8 day );
	void setHour( dm::uint8 hour );
	void setMinute( dm::uint8 minute );
	void setSec( dm::uint8 sec );
	void setMsec( dm::uint16 msec );

	void toTimeStamp( CTimeStamp& ts )const;
	CTimeStamp toTimeStamp()const;

	friend std::ostream& operator<<(std::ostream& ostr,const CDateTime& dt );

	std::string toString()const;
	bool fromString( const char* str );

	CDateTime today()const;
	CDateTime thisSunday()const;
	CDateTime thisMonth()const;
	CDateTime thisYear()const;

	CDateTime yesterday()const;
	CDateTime lastSunday()const;
	CDateTime lastMonth()const;
	CDateTime lastYear()const;

	CDateTime tomorrow()const;
	CDateTime nextSunday()const;
	CDateTime nextMonth()const;
	CDateTime nextYear()const;

	static CDateTime today( const CTimeStamp& now );
	static CDateTime thisSunday( const CTimeStamp& now );
	static CDateTime thisMonth( const CTimeStamp& now );
	static CDateTime thisYear( const CTimeStamp& now );

	static CDateTime yesterday( const CTimeStamp& now );
	static CDateTime lastSunday( const CTimeStamp& now );
	static CDateTime lastMonth( const CTimeStamp& now );
	static CDateTime lastYear( const CTimeStamp& now );

	static CDateTime tomorrow( const CTimeStamp& now );
	static CDateTime nextSunday( const CTimeStamp& now );
	static CDateTime nextMonth( const CTimeStamp& now );
	static CDateTime nextYear( const CTimeStamp& now );

	static CDateTime today( const CDateTime& now );
	static CDateTime thisSunday( const CDateTime& now );
	static CDateTime thisMonth( const CDateTime& now );
	static CDateTime thisYear( const CDateTime& now );

	static CDateTime yesterday( const CDateTime& now );
	static CDateTime lastSunday( const CDateTime& now );
	static CDateTime lastMonth( const CDateTime& now );
	static CDateTime lastYear( const CDateTime& now );

	static CDateTime tomorrow( const CDateTime& now );
	static CDateTime nextSunday( const CDateTime& now );
	static CDateTime nextMonth( const CDateTime& now );
	static CDateTime nextYear( const CDateTime& now );

	static const char* weekStr( const EWeekDay& wday );

	static bool getRtc( CDateTime& dc );
	static bool setRtc( const CDateTime& dc );
private:
	dm::uint16 m_year;	//!< 公元纪年。没有- 1900
	dm::uint8 m_month;	//!< 1~12
	dm::uint8 m_day;		//!< 1～31
	dm::uint8 m_hour;		//!< 0~23
	dm::uint8 m_minute;	//!< 0~59
	dm::uint8 m_sec;		//!< 0~59

	dm::uint16 m_msec;	//!< 0~999
};

}

#endif /* INCLUDE_DM_DATETIME_HPP_ */
